package com.hsurosy.hsuchain.nft.web.handler;

import com.google.common.collect.Maps;
import com.hsurosy.hsuchain.nft.base.exception.BizException;
import com.hsurosy.hsuchain.nft.base.exception.SystemException;
import org.springframework.http.HttpStatus;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;

import java.util.Map;

/**
 * 全局Web异常处理器
 *
 * @Author Hsu琛君珩
 * @Date 2024-10-05 5:14
 * @Description
 * @Version: v1.0.0
 */
@ControllerAdvice
public class GlobalWebExceptionHandler {

    /**
     * 处理方法参数校验异常
     * <p>
     * 当请求参数校验不通过时，会抛出 {@link MethodArgumentNotValidException}，该方法负责捕获并返回校验错误的字段和消息。
     *
     * @param ex 方法参数校验异常
     * @return Map<String, String> 包含字段名和错误消息的映射
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ResponseBody
    public Map<String, String> handleValidationExceptions(MethodArgumentNotValidException ex) {
        // 创建一个Map用于存储字段错误信息
        Map<String, String> errors = Maps.newHashMapWithExpectedSize(1);
        // 遍历校验错误，并提取字段名和错误消息
        ex.getBindingResult().getAllErrors().forEach((error) -> {
            String fieldName = ((FieldError) error).getField(); // 获取字段名
            String errorMessage = error.getDefaultMessage();    // 获取默认错误消息
            errors.put(fieldName, errorMessage);                // 将字段名和错误消息存入Map
        });
        return errors;
    }

    /**
     * 处理业务异常
     * <p>
     * 捕获 {@link BizException} 并返回统一的错误响应格式，包含错误码和错误消息。
     *
     * @param bizException 业务异常
     * @return Result 统一结果对象
     */
    @ExceptionHandler(BizException.class)
    @ResponseStatus(HttpStatus.OK)
    @ResponseBody
    public Result exceptionHandler(BizException bizException) {
        // 创建一个Result对象用于返回业务异常的响应
        Result result = new Result();
        result.setCode(bizException.getErrorCode().getCode());    // 设置错误码
        result.setMessage(bizException.getErrorCode().getMessage()); // 设置错误消息
        result.setSuccess(false); // 标记失败
        return result;
    }

    /**
     * 处理系统异常
     * <p>
     * 捕获 {@link SystemException} 并返回统一的错误响应格式，包含错误码和错误消息。
     *
     * @param systemException 系统异常
     * @return Result 统一结果对象
     */
    @ExceptionHandler(SystemException.class)
    @ResponseStatus(HttpStatus.OK)
    @ResponseBody
    public Result systemExceptionHandler(SystemException systemException) {
        // 创建一个Result对象用于返回系统异常的响应
        Result result = new Result();
        result.setCode(systemException.getErrorCode().getCode());    // 设置错误码
        result.setMessage(systemException.getErrorCode().getMessage()); // 设置错误消息
        result.setSuccess(false); // 标记失败
        return result;
    }
}
